package com.eian.boot.rabbit.aspect;

import com.eian.boot.rabbit.annotation.EnableRabbitRetry;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.amqp.AmqpException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Aspect
@Component
@ConditionalOnBean(annotation = EnableRabbitRetry.class)
public class RabbitRetryAspect {

    @Around("@annotation(com.eian.boot.rabbit.annotation.EnableRabbitRetry) && " +
            "execution(* com.eian.boot.rabbit.RabbitHelper.send(..))")
    public Object retrySend(ProceedingJoinPoint joinPoint) throws Throwable {
        final int maxRetry = 3;
        int retryCount = 0;
        long baseDelay = 1000L;

        while (true) {
            try {
                return joinPoint.proceed();
            } catch (AmqpException | InterruptedException e) {
                // 统一处理中断异常
                if (e instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                    throw e;
                }

                // 处理重试逻辑
                if (retryCount >= maxRetry) {
                    throw e;
                }

                // 添加随机因子避免惊群效应
                long delay = (long) (baseDelay * Math.pow(2, retryCount));
                long jitter = (long) (Math.random() * 1000);
                long finalDelay = delay + jitter;

                try {
                    TimeUnit.MILLISECONDS.sleep(finalDelay);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw e;
                }

                retryCount++;
            }
        }
    }
}